import {GameObjects, Scene, Tilemaps} from "phaser"

import {Player} from '../../classes/player'
import {Enemy} from '../../classes/enemy'
import {createLizardAnims} from "../../anims/EnemyAnims";

import {EVENTS_NAME} from "../../consts.ts";

export class GameScene extends Scene {
  private player!: Player
  private bg!: Phaser.GameObjects.TileSprite //用于显示可重复的瓷砖图像
  private map!: Tilemaps.Tilemap//在 Phaser 中，Tilemaps 是一个用于处理瓷砖地图的类，特别是在创建2D游戏时，它允许开发者创建复杂的关卡和环境。Tilemaps 提供了丰富的功能，以便能够加载、绘制和管理瓷砖地图
  private tileset!: Tilemaps.Tileset
  private wallsLayer!: Tilemaps.TilemapLayer
  // @ts-ignore
  private groundLayer!: Tilemaps.TilemapLayer
  private chests!: GameObjects.Sprite[]
  private enemies!: Enemy[]

  constructor() {
    super('game-scene')
  }

  create(props: any): void {
    createLizardAnims(this.anims)
    this.initMap(props.name)
    this.player = new Player(this, 100, 100)

    this.initChests()
    this.initEnemies()
    this.initCamera()

    this.physics.add.collider(this.player, this.wallsLayer) //添加碰撞器，进行物体之间检测
  }

  update(): void {
    this.bg?.setPosition() //用于设置游戏对象（如精灵、图形或其他元素）位置的方法
    this.player?.update();
  }

  private initMap(name: string): void {
    this.bg = this.add.tileSprite(0, 0, window.innerWidth, window.innerHeight, "water");//创建一个由单一纹理平铺而成的精灵，通常用于创建可以无限重读的背景或其他图形元素
    this.map = this.make.tilemap({
      key: 'tilemapGrass',
      // key: name,
      tileWidth: 16,
      tileHeight: 16,
    })
    // @ts-ignore
    this.tileset = this.map.addTilesetImage('Grass', 'Grass');//addTilesetImage 的第一个名称必须是和设计时的图块名称相同。
    // @ts-ignore
    this.groundLayer = this.map.createLayer('Ground', this.tileset, 0, 0)
    // @ts-ignore
    this.wallsLayer = this.map.createLayer('Walls', this.tileset, 0, 0);

    this.wallsLayer.setCollisionByProperty({collides: true}); //通过图块属性设置墙，碰撞属性开启

    this.physics.world.setBounds(0, 0, this.wallsLayer.width, this.wallsLayer.height);//设置世界的边缘

    // this.showDebugWalls()
  }

  // 同怪物一样，根据锚点先渲染出食物，不同的是当英雄和食物碰撞检测的回调不同，当英雄与食物重合，玩家可以获得 10 分。
  private initChests(): void {
    const chestPoints= this.map.filterObjects("Chests",(obj) => obj.name === "ChestPoint")
    // @ts-ignore
    this.chests = chestPoints.map((chestPoint) =>
      this.physics.add
        .sprite(
          chestPoint.x as number,
          chestPoint.y as number,
          "food",
          Math.floor(Math.random() * 8)
        )
        .setScale(0.5)
    )

    this.chests.forEach((chest) => {
        this.physics.add.overlap(this.player, chest, (obj1, obj2) => {
          this.game.events.emit(EVENTS_NAME.chestLoot)
          obj2.destroy()
        })
    })
  }

  private initEnemies(): void {
    //过去地图上的EnemyPoint点
    const enemiesPoints = this.map.filterObjects(
      'Enemies',
      (obj) => obj.name === 'EnemyPoint'
    )
    //实例化怪物
    // @ts-ignore
    this.enemies = enemiesPoints.map(
      (enemyPoint) =>
        new Enemy(
          this,
          enemyPoint.x as number,
          enemyPoint.y as number,
          'lizard',
          this.player
        )
    )

    // 怪物和墙增加碰撞检查
    this.physics.add.collider(this.enemies, this.wallsLayer)
    // 怪物和怪物增加碰撞检查
    this.physics.add.collider(this.enemies, this.enemies)
    // 怪物和角色增加碰撞检查
    // @ts-ignore
    this.physics.add.collider(
      this.player,
        this.enemies,
        (obj1,obj2) => {
        //碰撞后的回调，角色收到伤害-1
        (obj1 as Player).getDamage(1)
      },
      undefined,
      this
    )
  }

  // 相机跟随玩家角色移动
  private initCamera(): void {
    this.cameras.main.setSize(this.game.scale.width, this.game.scale.height) //设置相机大小: 确保相机覆盖整个游戏画布
    this.cameras.main.startFollow(this.player, true, 0.09, 0.09) //跟随玩家: 使相机跟随玩家角色的移动，平滑过渡。
    this.cameras.main.setZoom(2) //缩放视图: 将相机视图放大，使得玩家和场景的细节更加明显
  }

  private showDebugWalls(): void {
    const debugGraphics = this.add.graphics().setAlpha(0.7)
    this.wallsLayer.renderDebug(debugGraphics, {
      tileColor: null,
      collidingTileColor: new Phaser.Display.Color(243, 234, 48, 255),
    })
  }
}
